package com.gagakuai.concurrent;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.LockSupport;

/*
 * FutureTask表示一类将来会被完成的异步任务，这类任务带有返回值，且中途可被取消
 * 1:
 * 该类提供了Runnable与Future的基本实现，包括启动和取消任务，查询任务是否结束，以及获取任务执行结果。
 * 2:
 * 只有在任务结束后才能获取结果，如果任务尚未结束，get()方法将被阻塞。
 * 3:
 * 任务结束后，无法重新启动或取消计算，除非开始执行时调用的是runAndReset()。
 * 4:
 * FutureTask可用于包装Callable或Runnable型的任务，因为FutureTask实现了Runnable，所以可将FutureTask提交给Executor执行。
 * 5:
 * 除了作为独立的类使用，该类还定义了一些protected方法，以方便自定义子类。
 *
 * @author: houhong
 */
public class FutureTask<V> implements RunnableFuture<V> {

    /*
     * 任务状态标记
     */
    private volatile int state;

    /*
     * 新建任务
     */
    private static final int NEW = 0;

    /*
     * 任务已结束
     */
    private static final int COMPLETING = 1;
    /*
     * 任务正常结束
     */
    private static final int NORMAL = 2;

    /*
     * 任务异常结束，并设置了异常信息
     */
    private static final int EXCEPTIONAL = 3;
    /*
     * 任务已取消
     */
    private static final int CANCELLED = 4;
    /*
     * 任务正在中断
     */
    private static final int INTERRUPTING = 5;
    /*
     * 任务已中断
     */
    private static final int INTERRUPTED = 6;

    /*
     * 待执行任务（可由Runnable型任务包装而来）
     */
    private Callable<V> callable;
    /*
     * 保存正常结束下的计算结果或者 异常情况下的异常信息
     */
    private Object outcome;

    /*
     * 正在执行这个任务的线程
     */
    private volatile Thread runner;

    /*
     * 等待栈： 用于存储那些一些等待着计算结果的线程
     * 等待栈 的栈顶游标
     */
    private volatile WaitNode waiters;

    //保存 ruuner 的内存地址
    private static final VarHandle RUNNER;
    // 保存这【state】的内存地址
    private static final VarHandle STATE;
    // 保存着 【waiters】的内存地址
    private static final VarHandle WAITERS;

    static {
        try {
            MethodHandles.Lookup l = MethodHandles.lookup();
            RUNNER = l.findVarHandle(FutureTask.class, "runner", Thread.class);
            STATE = l.findVarHandle(FutureTask.class, "state", int.class);
            WAITERS = l.findVarHandle(FutureTask.class, "waiters", WaitNode.class);
        } catch (ReflectiveOperationException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    public FutureTask(Callable<V> callable) {
        if (callable == null) {
            throw new NullPointerException();
        }
        this.callable = callable;
        this.state = NEW;
    }

    public FutureTask(Runnable runnable, V result) {

        this.callable = Executors.callable(runnable, result);
        this.state = NEW;
    }

    /*▼ 执行 ████████████████████████████████████████████████████████████████████████████████┓ */

    /*
     * 执行任务，并设置执行结果，如果一切正常，state== NORMAL
     */
    @Override
    public void run() {

        // 尝试设置当前线程为任务执行线程，如果设置失败，直接返回
        if (!(state == NEW && compareAndSetRunner(null, Thread.currentThread()))) {
            return;
        }

        Callable<V> task = callable;

        if (task != null && state == NEW) {

            V result;
            boolean ran;

            try {
                // 执行任务，获取结果
                result = task.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                // 异常结束，设置异常信息，唤醒所有等待线程
                setException(ex);
            }
        }


    }


    /*▼ 获取结果 ████████████████████████████████████████████████████████████████████████████████┓ */


    /*
     * 只有在任务结束后才能获取结果，如果任务尚未结束，get()方法将被阻塞。
     */
    @Override
    public V get() throws InterruptedException, ExecutionException {

        int s = state;

        if (s <= COMPLETING) {
            // 获取任务的状态标记，任务未结束时会一直阻塞
            s = awaitDone(false, 0L);
        }
        //返回结果
        return report(s);
    }


    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        return false;
    }

    @Override
    public boolean isCancelled() {
        return false;
    }

    @Override
    public boolean isDone() {
        return false;
    }


    @Override
    public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        return null;
    }

    /*
     * 等待任务结束后，获取任务的状态标记，如果未启用超时，
     * 则一直阻塞，直到任务结束后被唤醒。否则，阻塞指定的一段时间后即退出
     */
    private int awaitDone(boolean timed, long nanos) throws InterruptedException {

        long startTime = 0L;

        //等待节点
        WaitNode waitNode;

        boolean queued = false;

        for (; ; ) {

            int s = state;

            //任务已经完成
            if (s >= COMPLETING) {

            } else if (true) {

            } else {
                //阻塞线程，进入等待
                LockSupport.park(this);
            }


        }

    }

    /*
     * 报告任务状态，返回任务的计算结果（可能会抛出异常）
     */
    private V report(int s) throws ExecutionException {

        Object res = outcome;

        // 如果是正常结束，返回计算结果
        if (s == NORMAL) {
            return (V) res;
        }
        // 如果是异常结束，抛出异常
        if (s >= CANCELLED) {
            throw new CancellationException();
        }
        throw new ExecutionException((Throwable) res);
    }

    /*
     * cas 设置runner
     */
    public final boolean compareAndSetRunner(Thread expect, Thread update) {

        return RUNNER.compareAndSet(this, expect, update);
    }

    /*
     * cas 设置等待游标
     */
    private final boolean compareAndSetWaiters(WaitNode expect, WaitNode update) {

        return WAITERS.compareAndSet(this, expect, update);
    }

    private final boolean compareAndSetState(int expect, int update) {

        return STATE.compareAndSet(this, expect, update);
    }

    /*
     * 设置异常
     * 并将任务状态从NEW更新为COMPLETING-->EXCEPTIONAL
     */
    protected void setException(Throwable t) {
        // 尝试更新任务状态：NEW-->COMPLETING
        if (compareAndSetState(NEW, COMPLETING)) {
            // 保存异常信息
            outcome = t;

            // 尝试更新任务状态：COMPLETING-->EXCEPTIONAL
            STATE.setRelease(this, EXCEPTIONAL); // final state

            // 任务结束后，唤醒所有等待线程
            finishCompletion();
        }
    }

    /*
     * 任务结束后,
     * 不管是正常结束，还是异常结束，或者是被取消），唤醒所有等待线程
     */
    private void finishCompletion() {

        // 遍历所有的等待线程
        WaitNode ptr = null;

        // spin
        for (; (ptr = waiters) != null; ) {
            //将等待栈 游标置为空
            if (compareAndSetWaiters(ptr, null)) {

                //唤醒所有的等待线程
                for (; ; ) {

                    WaitNode next = ptr.next;
                    Thread t = ptr.thread;
                    if (t != null) {
                        ptr.thread = null;
                        // 唤醒线程
                        LockSupport.unpark(t);
                    }


                    // 断开链表，help gc
                    ptr.next = null;
                    ptr = next;
                }

            }

        }

    }

    /* *
     *  组织为一个栈的数据结构
     */
    static final class WaitNode {

        // 正在等待计算结果的线程
        volatile Thread thread;
        //前一个等待结果
        volatile WaitNode next;

        public WaitNode(Thread thread, WaitNode next) {
            this.thread = thread;
            this.next = next;
        }
    }
}